//***************************************************************************************
// Default.hlsl by Frank Luna (C) 2015 All Rights Reserved.
//***************************************************************************************

// Defaults for number of lights.
#ifndef NUM_DIR_LIGHTS
    #define NUM_DIR_LIGHTS 3
#endif

#ifndef NUM_POINT_LIGHTS
    #define NUM_POINT_LIGHTS 0
#endif

#ifndef NUM_SPOT_LIGHTS
    #define NUM_SPOT_LIGHTS 0
#endif

//// Include common HLSL code.


struct MaterialObjData
{
	uint m_inxTexHeap[2];
	float4 m_veDiffuseAlbedo;
	float4 m_veFresnelR0;
	float m_fRoughness;
	float4 m_matTransform;
};


TextureCube gCubeMap : register(t0);

// An array of textures, which is only supported in shader model 5.1+.  Unlike Texture2DArray, the textures
// in this array can be different sizes and formats, making it more flexible than texture arrays.
Texture2D gTextureMaps[48] : register(t1);

StructuredBuffer<MaterialObjData> gMaterialData : register(t0, space1);

SamplerState gsamPointWrap        : register(s0);
SamplerState gsamPointClamp       : register(s1);
SamplerState gsamLinearWrap       : register(s2);
SamplerState gsamLinearClamp      : register(s3);
SamplerState gsamAnisotropicWrap  : register(s4);
SamplerState gsamAnisotropicClamp : register(s5);
SamplerComparisonState gsamShadow : register(s6);


// Constant data that varies per frame.
cbuffer ObjectConstantsBuffer : register(b0)
{
	int m_inxLight[8];
	float4x4 m_matWorld;
	int     m_inxMaterial;
};


cbuffer cbSkinned : register(b1)
{
	float4x4 gBoneTransforms[96];
};

cbuffer CameraData: register(b2)
{
	// Camera coordinate system with coordinates relative to world space.
	float3 mPosition;
	float3 mRight;
	float3 mUp;
	float3 mLook;

	// Cache frustum properties.
	float mNearZ;
	float mFarZ;
	float mAspect;
	float mFovY;
	float mNearWindowHeight;
	float mFarWindowHeight;

	int mViewDirty;

	// Cache View/Proj matrices.
	float4 mView;
	float4 mProj;
};

cbuffer LightData : register(b3)
{
	int m_isEnable;
	int m_iLightType;
	float3 m_lightStrength;
	float m_fFalloffStart;                          // point/spot light only
	float3 m_veDirection;// directional/spot light only
	float m_fFalloffEnd;                           // point/spot light only
	float3 m_vePosition;  // point/spot light only
	float m_fSpotPower;                            // spot light only
};

struct VertexIn
{
	float3 PosL    : POSITION;
	float3 NormalL : NORMAL;
	float2 TexC    : TEXCOORD;
	float3 TangentL : TANGENT;
#ifdef SKINNED
	float3 BoneWeights : WEIGHTS;
	uint4 BoneIndices  : BONEINDICES;
#endif
};


struct VertexOut
{
	float4 PosH    : SV_POSITION;
//    float4 ShadowPosH : POSITION0;
 //   float4 SsaoPosH   : POSITION1;
  //  float3 PosW    : POSITION2;
    float3 NormalW : NORMAL;
	float3 TangentW : TANGENT;
	float2 TexC    : TEXCOORD;
};

VertexOut VS(VertexIn vin)
{
	VertexOut vout;
	// Fetch the material data.
	MaterialObjData matData = gMaterialData[m_inxMaterial];

	// Transform to homogeneous clip space.
	vout.PosH = mul(float4(vin.PosL, 1.0f), m_matWorld);
	vout.NormalW = mul(float4(vin.NormalL, 1.0f), m_matWorld);
	vout.NormalW = normalize(vout.NormalW);
	// Just pass vertex color into the pixel shader.
	vout.TangentW = mul(float4(vin.TangentL, 1.0f), m_matWorld);
	vout.TangentW = normalize(vout.TangentW);

	float4 texC = mul(float4(vin.TexC, 0.0f, 1.0f), matData.m_matTransform);
	vout.TexC = texC.xy;

	return vout;
}

float4 PS(VertexOut pin) : SV_Target
{
	MaterialObjData matData = gMaterialData[m_inxMaterial];

	uint diffuseMapIndex = matData.m_inxTexHeap[0];
	return gTextureMaps[diffuseMapIndex].Sample(gsamAnisotropicWrap, pin.TexC);

}

